package com.eduadmin.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.fastjson.JSON;
import com.eduadmin.entity.Grade;
import com.eduadmin.entity.Score;
import com.eduadmin.entity.Student;
import com.eduadmin.exception.CustomException;
import com.eduadmin.service.IGradeService;
import com.eduadmin.service.IScoreService;
import com.eduadmin.service.IStudentService;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class ScoreDataUploadListener extends AnalysisEventListener<Score> {
    private int count = 1;         //解析的数据行数
    private List<String> errors = new ArrayList<>();
    List<Score> scores = new ArrayList<>();
    //封装查询参数 把年级数据库表名 和 成绩数据 进行封装
    Map<String, Object> maps = new HashMap<>();

    private final IScoreService scoreService;
    private final IStudentService studentService;
    private final String gradeDatatableName;
    private final String gradeName;

    public ScoreDataUploadListener(IStudentService studentService, IScoreService scoreService, String gradeDatatableName, String gradeName) {
        this.scoreService = scoreService;
        this.studentService = studentService;
        this.gradeDatatableName = gradeDatatableName;
        this.gradeName = gradeName;
    }

    @Override
    public void invoke(Score data, AnalysisContext context) {
        log.info("解析到一条数据:{}", JSON.toJSONString(data));
        count++;
        String studentIdCard = data.getStudentIdCard();
        if (data.getGradeName().equals(gradeName) && data.getTeamName().contains(data.getGradeName())) {
            maps.put("gradeDatatableName", gradeDatatableName);
            maps.put("gradeName", gradeName);
            maps.put("teamName", data.getTeamName());
            maps.put("semesterName", data.getSemesterName());
            maps.put("examName", data.getExamName());
            maps.put("studentIdCard", studentIdCard);
            //判断身份证号在学生表中
            Student student = studentService.getStudentByIdcard(studentIdCard);
            if (student != null ) {//身份证号在学生表中
                 //判断成绩唯一
                if(scoreService.getScoreUnique(maps) == null){
                    scores.clear();
                    scores.add(data);
                    saveData();
                }else{
                    errors.add("Excel 数据表中第 " + count + " 行信息已经在数据库中，不能导入！");
                }
            } else {
                errors.add("Excel 数据表中第 " + count + " 行信息中学生身份证号没有在学生库中，不能导入！");
            }
        } else {
            errors.add("Excel 数据表中第 " + count + " 行信息的年级班级错误，不能导入！");
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        log.info("所有数据解析完成！");
        //抛自定义异常 如果有错误
        if (errors.size() > 0) {
            throw new CustomException("/adminindex", "", errors);
        }
    }

    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException e = (ExcelDataConvertException) exception;
            errors.add("数据解析异常，所在行：" + e.getRowIndex() + " ，所在列：" + e.getColumnIndex() + " ，数据是:" + e.getCellData());
        }
    }

    private void saveData() {
        log.info("{}条数据，开始存储数据库！", this.count);
        if (!CollectionUtils.isEmpty(scores)) {
            maps.clear();
            maps.put("scores", scores);
            maps.put("gradeDatatableName", gradeDatatableName);
            scoreService.addScores(maps);
        }
        log.info("存储数据库成功！");
    }

    //18位身份证校验
    public boolean isCard(String id) {
        int[] w = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
        char[] c = id.toCharArray();
        int sum = 0;
        for (int i = 0; i < w.length; i++) {
            sum += (c[i] - '0') * w[i];
        }
        char[] verifyCode = "10X98765432".toCharArray();
        char ch = verifyCode[sum % 11];
        return c[17] == ch;
    }
}
